package at.ac.tuwien.dse.health.admin.jdbc

import java.sql.{PreparedStatement, Connection}
import java.io.Closeable

/** Contains convenience methods for [[at.ac.tuwien.dse.health.admin.jdbc.PreparedStatementHolder]]. */
object PreparedStatementHolder {
	/** Creates a [[at.ac.tuwien.dse.health.admin.jdbc.PreparedStatementHolder]] */
	def apply(psc: (Connection) => PreparedStatement)(implicit jdbcTemplate: JdbcTemplate) = new PreparedStatementHolder(jdbcTemplate, psc(jdbcTemplate.conn))
}

/** Contains data for creating a [[java.sql.PreparedStatement]] ondemand and executes it using a [[at.ac.tuwien.dse.health.admin.jdbc.JdbcTemplate]]. */
class PreparedStatementHolder(jdbcTemplate: JdbcTemplate, sql: String) extends Closeable {
	var args: Array[Any] = Array()
	var pstmt: PreparedStatement = _

	def this(jdbcTemplate: JdbcTemplate, pstmt: PreparedStatement) = {
		this(jdbcTemplate, "")
		this.pstmt = pstmt
	}

	/** Sets the arguments to use for preparing the SQL statement. */
	def withArgs(args: Array[Any]) = {
		this.pstmt = null
		this.args = args
		this
	}

	/** Executes the SQL query and returns the number of rows affected. */
	def update() = {
		stmt()
		jdbcTemplate update this
	}

	/** Returns the [[java.sql.ResultSet]] of the executed SQL query. */
	def result() = {
		stmt()
		jdbcTemplate query this
	}

	/** Returns the of the executed SQL query after applying the given [[at.ac.tuwien.dse.health.admin.jdbc.RowMapper]]. */
	def use[T](rowMapper: RowMapper[T]) = {
		stmt()
		jdbcTemplate query(this, rowMapper)
	}

	/** Creates a [[java.sql.PreparedStatement]] if necessary. */
	def stmt(conn: Connection = jdbcTemplate.conn) = {
		if (pstmt == null) {
			pstmt = conn prepareStatement sql
			1 to args.size foreach (i => pstmt setObject(i, args(i)))
		}
		pstmt
	}

	override def close() {
		if (pstmt != null) pstmt.close
	}
}
